﻿#include "RpcCallback.h"
#include "XyNet/Channel/RpcSocketChannel.h"
#include "XyNet/Endpoint/RpcEndpoint.h"
#include "XyNet/Protocol/cpp/Rpc.service.h"
#include "XyNet/Service/RpcController.h"
#include "XyNet/Service/RpcArgument.h"

namespace XyNet
{
	RpcCallback::RpcCallback(shared_ptr<RpcArgument> argument)
		: _argument(argument), _createTime(chrono::steady_clock::now()) {}

	RpcCallback::~RpcCallback()
	{
		stopTimer();
	}

	shared_ptr<RpcArgument> RpcCallback::getArgument()
	{
		return _argument;
	}

	const chrono::steady_clock::time_point& RpcCallback::getCreateTime() const
	{
		return _createTime;
	}

	void RpcCallback::run()
	{
		// 先停止计时器
		stopTimer();

		// 检查是否处理完控制器异常，如果没有，这里抛出异常
		auto controller = _argument->getController();
		if (!controller->isFailed())
		{
			doResponseHandler();
		}
		else
		{
			doExceptionHandler();
		}
	}

	void RpcCallback::startTimer(
		RpcSocketChannel* socketChannel, const Id& messageId)
	{
		RpcEndpoint* endpoint = socketChannel->getEndpoint();
		_timer = make_shared<boost::asio::deadline_timer>(*endpoint->getIoService());
		_timer->expires_from_now(boost::posix_time::seconds(
			endpoint->getConfig()->getMessageTimeout()));
		_timer->async_wait(bind(&RpcCallback::onTimeOut,
			endpoint, socketChannel->getId(), messageId, boost::asio::placeholders::error));
	}

	void RpcCallback::stopTimer()
	{
		if (_timer)
			_timer->cancel();
	}

	void RpcCallback::onTimeOut(RpcEndpoint* endpoint, const Id& socketChannelId,
		const Id& messageId, const boost::system::error_code& error)
	{
		// 对于任何时间未到的 timer，只要对该 timer 做了 cancel 或者 expires_xxx 操作，
		// 该 timer 原先登记的 handler 都会被调用，并且 err 为 true。
		if (!error)
		{
			auto socketChannel = endpoint->findSocketChannel(socketChannelId);
			if (socketChannel)
				socketChannel->setFailedCallback(messageId, RpcErrors::Timeout);
		}
	}
}